package com.rest.core.client;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.log4j.Logger;
import org.glassfish.jersey.apache.connector.ApacheClientProperties;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
import org.springframework.util.CollectionUtils;

public class HttpClientUtil {

	final static Logger logger = Logger.getLogger(HttpClientUtil.class);

	private Client client;

	public Client getClient() {
		return client;
	}

	public HttpClientUtil() {
		buildClient();
	}

	private void buildClient() {
		final ClientConfig clientConfig = new ClientConfig();
		final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
		cm.setMaxTotal(20000);
		cm.setDefaultMaxPerRoute(10000);
		clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, cm);
		clientConfig.connectorProvider(new GrizzlyConnectorProvider());
		client = ClientBuilder.newClient(clientConfig);
	}
	
	/**
	 * REST - GET请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:24:15 
	 * @param url：请求URL
	 * @return
	 */
	public String GET(String url) {
		return rest("GET", url, null, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, null);
	}
	
	/**
	 * REST - GET请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:24:15 
	 * @param url：请求URL
	 * @param queryParams：请求参数
	 * @return
	 */
	public String GET(String url, Map<String, Object> queryParams) {
		return rest("GET", url, null, queryParams,
				MediaType.APPLICATION_JSON_TYPE, String.class, null);
	}
	
	/**
	 * REST - GET请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:25:47 
	 * @param url：请求URL
	 * @param queryParams：请求参数
	 * @param returnType：请求返回类型
	 * @return
	 */
	public <T> T GET(String url, Map<String, Object> queryParams,
			Class<T> returnType) {
		return rest("GET", url, null, queryParams,
				MediaType.APPLICATION_JSON_TYPE, returnType, null);
	}
	
	/**
	 * REST - POST请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:28:36 
	 * @param url：请求URL
	 * @param requestDate：请求参数
	 * @return
	 */
	public String POST(String url, Map<String, Object> requestDate) {
		return rest("POST", url, null, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, requestDate);
	}
	
	/**
	 * REST - POST请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:31:55 
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @param requestDate：请求参数
	 * @return
	 */
	public String POST(String url, Map<String, Object> headParams,
			Map<String, Object> requestDate) {
		return rest("POST", url, headParams, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, requestDate);
	}
	
	/**
	 * REST - POST请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:31:55 
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @param returnType：请求返回类型
	 * @param requestDate：请求参数
	 * @return
	 */
	public <T> T POST(String url, Map<String, Object> headParams,
			Class<T> returnType, Map<String, Object> requestDate) {
		return rest("POST", url, headParams, null,
				MediaType.APPLICATION_JSON_TYPE, returnType, requestDate);
	}
	
	/**
	 * REST - PUT请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:32:54 
	 * @param url：请求URL
	 * @param requestDate：请求参数
	 * @return
	 */
	public String PUT(String url, Map<String, Object> requestDate) {
		return rest("PUT", url, null, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, requestDate);
	}
	
	/**
	 * REST - PUT请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午1:09:01 
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @param requestDate：请求参数
	 * @return
	 */
	public String PUT(String url, Map<String, Object> headParams,
			Map<String, Object> requestDate) {
		return rest("PUT", url, headParams, null,
				MediaType.APPLICATION_JSON_TYPE, String.class, requestDate);
	}
	
	/**
	 * REST - PUT请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:31:55 
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @param returnType：请求返回类型
	 * @param requestDate：请求参数
	 * @return
	 */
	public <T> T PUT(String url, Map<String, Object> headParams,
			Class<T> returnType, Map<String, Object> requestDate) {
		return rest("PUT", url, headParams, null,
				MediaType.APPLICATION_JSON_TYPE, returnType, requestDate);
	}
	
	
	/**
	 * REST - DELETE请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:41:49 
	 * @param url：请求URL
	 * @return
	 */
	public String DELETE(String url) {
		return rest("DELETE", url, null, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, null);
	}
	
	/**
	 * REST - DELETE请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:41:49 
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @return
	 */
	public String DELETE(String url, Map<String, Object> headParams) {
		return rest("DELETE", url, headParams, null,
				MediaType.APPLICATION_JSON_TYPE, String.class, null);
	}
	
	
	/**
	 * REST 请求
	 * @Description: 
	 * @author Smile- 2016年4月23日 下午12:19:15 
	 * @param method：请求方法类型
	 * @param url：请求URL
	 * @param headParams：请求头信息
	 * @param queryParams：GET请求参数
	 * @param requestDataType：请求媒体类型
	 * @param returnType：请求返回类型
	 * @param requestDate：POST/PUT请求参数
	 * @return
	 */
	public <T> T rest(String method, String url,
			Map<String, Object> headParams, Map<String, Object> queryParams,
			MediaType requestDataType, Class<T> returnType,
			Map<String, Object> requestDate) {
		// 构造WebTarget
		WebTarget webTarget = client.target(url);
		if (!CollectionUtils.isEmpty(queryParams)) {
			Set<String> keySet = queryParams.keySet();
			for (String key : keySet) {
				webTarget = webTarget.queryParam(key, queryParams.get(key));
			}
		}
		// 构造Builder
		Builder builder = webTarget.request(requestDataType);
		if (!CollectionUtils.isEmpty(headParams)) {
			Set<String> keySet = headParams.keySet();
			for (String key : keySet) {
				builder.header(key, headParams.get(key));
			}
		}
		// 发起请求和处理结果
		Response response;
		Form form = new Form();
		if (!CollectionUtils.isEmpty(requestDate)) {
			Set<String> keySet = requestDate.keySet();
			for (String key : keySet) {
				form.param(key, requestDate.get(key).toString());
			}
		}
		method = method.toUpperCase();
		if ("GET".equals(method)) {
			response = builder.get();
			return response.readEntity(returnType);
		} else if ("DELETE".equals(method)) {
			response = builder.delete();
			return response.readEntity(returnType);
		} else if ("PUT".equals(method)) {
			response = builder.put(Entity.form(form));
			return response.readEntity(returnType);
		} else if ("POST".equals(method)) {
			response = builder.post(Entity.form(form));
			return response.readEntity(returnType);
		} else {
			return null;
		}
	}

	public static void main(String[] args) {
		HttpClientUtil http = new HttpClientUtil();
		Map<String, Object> headParams = new HashMap<String, Object>();
		Map<String, Object> queryParams = new HashMap<String, Object>();
		Map<String, Object> map = new HashMap<String, Object>();
		String rest = http.rest("get", "http://localhost:8080/api/books",
				queryParams, null, MediaType.APPLICATION_JSON_TYPE,
				String.class, null);
		System.out.println(rest);
		System.out.println("==================================");
		String url = "http://localhost:8080/api/books";
		String get = http.GET(url, null);
		System.out.println(get);
		System.out.println("==================================");
		map.put("bookName", "restbookName");
		map.put("author", "restAuthor");
		headParams.put("toke", "123456789");
		String post = http.POST(url, headParams, String.class, map);
		System.out.println(post);
		System.out.println("==================================");
		map.put("bookName", "restbookName2");
		map.put("author", "restAuthor2");
		map.put("id", "31");
		String put = http.PUT(url, headParams, String.class, map);
		System.out.println(put);
		System.out.println("==================================");
		String delete = http.DELETE(url + "/31", headParams);
		System.out.println(delete);
		http.client.close();

	}
}
